package sql

import (
	"bytes"
	"errors"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"text/template"
	"time"
)

// RootTmpl 模板根实体
type RootTmpl struct {
	root  string    //模板根目录地址
	cache *sync.Map //全部模板map
}

// 单一模板实体
type item struct {
	tmpl    *template.Template //模板便来给你
	relPath string             //真是路径
	modTime time.Time          //最后修改时间
}

// New 新建根目录的方法
func New(root string) *RootTmpl {
	return &RootTmpl{
		root:  root,
		cache: &sync.Map{},
	}
}

// 加载模板的方法
func (st *RootTmpl) loadTmpl(relPath string) (*template.Template, error) {
	if v, ok := st.cache.Load(relPath); ok {
		if item := v.(*item); st.isCacheItemValid(item) {
			return item.tmpl, nil
		}
	}
	//load
	fullPath := filepath.Join(st.root, relPath)
	fi, err := os.Stat(fullPath)
	if err != nil {
		return nil, err
	}
	buf, err := os.ReadFile(fullPath)
	if err != nil {
		return nil, err
	}
	//tmpl, err := template.New(relPath).Funcs(funcMap).Parse(string(buf))
	tmpl, err := template.New(relPath).Parse(string(buf))
	if err != nil {
		return nil, err
	}
	st.cache.Store(relPath, &item{tmpl, relPath, fi.ModTime()})
	return tmpl, nil
}

// 判断脚本文件的最后修改时间是否与现存模板一致
func (st *RootTmpl) isCacheItemValid(item *item) bool {
	if fi, err := os.Stat(filepath.Join(st.root, item.relPath)); err != nil {
		return false //(如果文件不存在, 不报错)
	} else {
		return fi.ModTime().Equal(item.modTime)
	}
}

func (st *RootTmpl) GetSql(ident string, dot any) (string, error) {
	i := strings.LastIndex(ident, ".")
	if i == -1 {
		return "", errors.New("ident格式错误")
	}
	relpath, name := ident[:i], ident[i+1:]
	tmpl, err := st.loadTmpl(relpath + ".sql")
	if err != nil {
		return "", err
	}
	var buf bytes.Buffer
	err = tmpl.ExecuteTemplate(&buf, name, dot)
	if err != nil {
		return "", err
	}
	return buf.String(), nil
}
